<?php
/** Yz_SQL_Statement
*
*/

class Yz_SQL_Statement
    extends Yz_Class
    implements Yz_SQL_Statement_Interface
{

    /** The SQL code of the query
     *  @var string
     */
    protected $sql;

    /**
     *  @var Yz_SQL_Adapter_Interface&
     */
    protected $db;

    /**
     *  The hash of bound parameters
     *  @var array
     */
    protected $bound = array();

    /**
     *  Whether the query has been executed
     *  @var bool
     */
    protected $queryDone = false;

    /**
    *   create statement of general type with options
    *
    *   @param ???
    *   @return new Statement
    */
    final public static function create( $connectionName=null )
    {
        debug();

        $conn = Yz_SQL_Adapter::selectConnection($connectionName);

        return new static( $conn );
    } // create



    /** __construct()
    *
    *
    */
    protected function __construct( $connection )
    {
        debug();

        $this->db = $connection;
    } // __construct



    /** query() :
    *
    *
    */
    public function query( $sql )
    {
        assert('is_string($sql)');
        $this->sql = $sql;
        return $this;
    } // query()


    /** getSQL() : get the string representation of the current statement
    *
    *
    */
    public function getSQL()
    {
        return $this->sql;
    } // getSQL()



    /** TODO must be a possibility to execute query as prepared stmt
    *
    *   @return <this>
    */
    public function execute()
    {
        debug();

        if ($this->bound) {
            $esql = strtr($this->sql, $this->bound);
        } else {
            $esql = $this->sql;
        }

        $this->db->execute( $esql );

        $this->queryDone = true;
        return $this;
    } // execute



    /** TODO quote by type
    *
    *   @return <this>
    */
    public function bind( $param, $value )
    {
        debug();

        if (null === $value) {
            $value = 'NULL';
        } else if (true === $value) {
            $value = 'TRUE';
        } else if (false === $value) {
            $value = 'FALSE';
        } else if ($value instanceof Yz_SQL_Literal) {
            $value = "$value";
        } else if (is_object($value)) {
            $value = $this->db->quote("$value");
        } else {
            $value = $this->db->quote( Yz_String::test($value) );
        }
        return $this->_bind( $param, $value );
    } // bind

    /**
    *
    *   @return <this>
    */
    public function bindArray( $values )
    {
        debug();
        $valuesArray = Yz_Hash::test($values);
        if (! $valuesArray)
            throw ValueError::_new_();
        foreach ($valuesArray as $param => $value)
            $this->bind($param, $value);
        return $this;
    } // bindArray

    /**
    *
    */
    public function count()
    {
        return $this->db->count();
    } // getAffectedRows


    protected function testQueryDone()
    {
        assert('!!$this->queryDone');
        return $this;
    } // testqueryDone

    protected function _bind( $param, $value )
    {
        $param = Yz_String::test($param);
        if (! $param)
            throw ValueError::_new_();
        $this->bound[":".$param] = $value;
        return $this;
    }

    /**
     *
     */
    protected function _quoteIdentifier($ident)
    {
        debug();
        return $this->db->quoteIdentifier($ident);
    }

} // class

